#include <iostream>
#include <vector>
#include <algorithm>

class Student {
    private:
        std::string name;
        int age;
        double score;
    public:
        Student(std::string name, int age, double score):
        name{name}, age{age}, score{score} {
            std::cout << "Student() init" << std::endl;
        }

        std::string& get_name() {
            return name;
        }
        int get_age() const{
            return age;
        }
        double get_score() {
            return score;
        }
        void print() const {
            std::cout << "name: " << name << " age: " << age << " score: " << score << std::endl;

        }
};

void find_item()
{
    std::cout << "find_item=========================" << std::endl;
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    // 查找元素找到时会返回元素对应得迭代器指针
    auto it = std::find(v.begin(), v.end(), 5);
    std::vector<int>::iterator it2 = v.begin();
    while(it2 != v.end()) {
        std::cout << *it2 << " ";
        it2++;

    }

    if (it == v.end()) // 说明没有找到 元素
    {
        std::cout << "not found" << std::endl;
    }
    else
    {
        std::cout << "found" << *it << std::endl;
        *it = 100; // 替换元素值
    }

    for (auto &i : v)
    {
        std::cout << i << " ";
    }
}

bool findStr(std::string_view str) {
    return (str.find("hello") != std::string::npos);
}
void find_item_if() {
    std::vector<std::string> vstr = {"hello", "world", "c++", "algorithm", "learn"}; 
    auto it = std::find_if(vstr.begin(), vstr.end(), findStr);
    if (it != vstr.end()) {
        std::cout << "find item: " << *it << std::endl;
    } else  {
        std::cout << "not find item" << std::endl;
    }
}

bool find_student(Student& student) {

    if (student.get_age() >= 19)
    {
        return true;
    }
    return false;
    
}
void find_item_obj() {
    std::vector<Student> students{};
    students.reserve(3);
    //students.emplace_back("zhangsan", 18);
    //std::vector<Student> vstudent = {{"xiaoming", 18, 18.1}, {"xiaohong", 19, 19.1}, {"xiaoli", 20, 20.1}};
    //使用临时对象构建，临时对象使用使用构造函数（临时对象在函数结束时会销毁）
    students.push_back(Student{"xiaoming", 18, 18.1});
    students.push_back({"xiaohong", 19, 19.1});
    students.push_back({"xiaoli", 20, 20.1});

    auto it = std::find_if(students.begin(), students.end(), find_student);
    
    if (it != students.end())
    {
        std::cout << "find student:" << it->get_name() << std::endl;
    } else {
        std::cout << "not find student" << std::endl;
    }  

    // lambda 过滤
    auto it2 = std::find_if(students.begin(), students.end(), [](Student& stu) {
        if (stu.get_score() >= 22) {
            return true;
        }
        return false;
    });

    if (it2 != students.end()) {
        std::cout << "find student:" << it2->get_name() << std::endl;
    } else {
        auto ittmp = it2 - 1;
        std::cout << "not find student" << ittmp -> get_name()<< std::endl;
    };

    // 查找多个结果(这只是一种思路，还不如直接使用迭代器直接过滤)
    auto it3 = std::vector<Student>::iterator{students.begin()};
    while (it3 != students.end()) {
        auto tempit = std::find_if(it3, students.end(), [](Student& stu) {
            if (stu.get_score() >= 18) {
                return true;
            }
            return false;
        });

        std::cout << "name: " << tempit->get_name() << " score: " << tempit->get_score() << std::endl;

        if (tempit != students.end()) {
            it3 = tempit;
            it3++;
        } else {
            it3 = tempit;
        }
    }
}

bool count_if_func(std::string_view str) {
    return (str.find("nut") != std::string_view::npos);
}
void count_item() {
    std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 5, 9, 10};
    auto it = std::count(vec.begin(), vec.end(), 5);
    std::cout << "count: " << it << std::endl;
}

void count_item_if() {
    std::array<std::string_view, 5> arr{ "apple", "banana", "walnut", "lemon", "peanut" };
    auto nuts = std::count_if(arr.begin(), arr.end(), count_if_func);
    std::cout << "Counted " << nuts << " nut(s)\n";
}

void sort_item() {
    std::vector<int> vec = { 5, 1, 4, 2, 3 };
    std::sort(vec.begin(), vec.end(), [](int a, int b) {
        return a > b;
    });
    for (auto i : vec) {
        std::cout << i << " ";
    }
}

void algorithm_learn()
{
    find_item();
    std::cout << "-------find_if-----------------" << std::endl;
    find_item_if();
    find_item_obj();
    std::cout << "-------std::count-----------------" << std::endl;
    count_item();
    count_item_if();
    std::cout << "-------std::sort-----------------" << std::endl;
    sort_item();
}